﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GoogleFinance;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.ComponentModel;
using System.Threading;
using System.ServiceModel.Syndication;
using YahooFinance;

namespace ViewModel
{
    /// <summary>
    /// The view model for the main window
    /// </summary>
    public class MainWindowViewModel : ViewModelBase, IDisposable
    {
        private readonly StockQuotes googleFinanceApi;
        private readonly News newsServiceApi;
        private ThreadedObservableCollection<StockQuote> _stockQuotes;
        private ThreadedObservableCollection<NewsItem> _news;
        private Timer updateTimer;
        private bool disposed;
        private string[] ftse = "AAL.L,ABF.L,AMEC.L,ANTO.L,ARM.L,AZN.L,BARC.L,BATS.L,BG.L,BLND.L,BLT.L,BP.L,BRBY.L,BSY.L,CCL.L,CNA.L,CNE.L,CPG.L,CPI.L,CSCG.L,DGE.L,EMG.L,ENRC.L,ESSR.L,EXPN.L,FRES.L,GFS.L,GKN.L,GLEN.L,GSK.L,hMSO.L,HSBA.L,IAP.L,IHG.L,III.L,IMI.L,IMT.L,INVP.L,IPR.L,ITRK.L,ITV.L,MKS.L".Split(',');

        /// <summary>
        /// Main window default constructor
        /// </summary>
        public MainWindowViewModel()
        {
            googleFinanceApi = new StockQuotes();
            newsServiceApi = new News();
            PropertyChanged += new PropertyChangedEventHandler(MainWindowViewModel_PropertyChanged);
        }

        private void MainWindowViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "StockQuoteSelectedItem":
                    StockQuoteSelectedItem_PropertyChanged();
                    break;
            }
        }

        /// <summary>
        /// Called when view model is started
        /// </summary>
        public override void OnStartup()
        {
            base.OnStartup();

            StockQuotes = new ThreadedObservableCollection<StockQuote>(new List<StockQuote>());
                     
            InitializeTimer();
        }

        private void StockQuoteSelectedItem_PropertyChanged()
        {
            ThreadPool.QueueUserWorkItem(
                new WaitCallback(SetNews), _stockQuoteSelectedItem.Symbol
                );
            ChartSource = Helpers.GetChartUrlForSymbol(_stockQuoteSelectedItem.Symbol, 300, 400);
            string symbolLse = String.Format("LSE:{0}", _stockQuoteSelectedItem.Symbol.Replace(".L", String.Empty));
            HistoricalChartSource = String.Format("http://www.bbc.co.uk/news/business/market_data/chart?chart_primary_ticker={0}&chart_time_period=12_month&canvas_colour=000000&primary_chart_colour=CC0000&use_transparency=0&plot_colour=ffffff&cp_line_colour=1F4F82&margin_left=35&margin_bottom=20&margin_right=20&time_24hr=1&tiny_chart=1&tiny_month_view=1&logo_strength=light&y_axis_left=1&x_axis_plain=1&cp_line=1&cp_line_style=dotline&charting_freq=1_minute&co_dimension^width=400&co_dimension^height=300", symbolLse);
        }

        private void InitializeTimer()
        {
            updateTimer = new Timer(TimerTick, null, 0, 5000);
        }

        private void TimerTick(object state)
        {
            UpdateQuotes();
        }

        private void UpdateQuotes()
        {
            IList<StockQuote> newQuotes = googleFinanceApi.GetQuotesForSymbols(ftse);
            foreach (StockQuote newQuote in newQuotes)
            {
                StockQuote existingQuote = StockQuotes.FirstOrDefault(f => f.Symbol == newQuote.Symbol);
                if (existingQuote != null)
                    existingQuote.CopyProperties(newQuote);
                else
                    StockQuotes.Add(newQuote);
            }
        }

        /// <summary>
        /// ThreadedObservableCollection of stock quotes
        /// </summary>
        public ThreadedObservableCollection<StockQuote> StockQuotes
        {
            get
            {
                return _stockQuotes;
            }
            set
            {
                _stockQuotes = value;
                OnPropertyChanged("StockQuotes");
            }
        }

        /// <summary>
        /// ThreadedObservableCollection of news items
        /// </summary>
        public ThreadedObservableCollection<NewsItem> News
        {
            get
            {
                return _news;
            }
            set
            {
                _news = value;
                OnPropertyChanged("News");
            }
        }

        private void SetNews(Object stateInfo)
        {
            string symbol = (string)stateInfo;
            News = new ThreadedObservableCollection<NewsItem>(
                           newsServiceApi.GetNewsForSymbol(symbol)
                           );
        }

        private StockQuote _stockQuoteSelectedItem;
        /// <summary>
        /// The currently selected Stock Quote object
        /// </summary>
        public StockQuote StockQuoteSelectedItem 
        {
            get
            {
                return _stockQuoteSelectedItem;
            }
            set
            {
                if (_stockQuoteSelectedItem != value)
                {
                    _stockQuoteSelectedItem = value;
                    OnPropertyChanged("StockQuoteSelectedItem");
                }
                
            }
        }

        private string _chartSource;
        /// <summary>
        /// The current URL for the intra-day chart
        /// </summary>
        public string ChartSource
        {
            get
            {
                return _chartSource;
            }
            set
            {
                if (_chartSource != value)
                {
                    _chartSource = value;
                    OnPropertyChanged("ChartSource");
                }
            }
        }


        private string _historicalChartSource;
        /// <summary>
        /// The current URL for the historical chart. 
        /// </summary>
        public string HistoricalChartSource
        {
            get
            {
                return _historicalChartSource;
            }
            set
            {
                if (_historicalChartSource != value)
                {
                    _historicalChartSource = value;
                    OnPropertyChanged("HistoricalChartSource");
                }
            }
        }

        #region IDisposable Members

        /// <summary>
        /// Called to dispose the object
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Called to dispose the object
        /// </summary>
        /// <param name="disposing">If disposing equals true, the method has been called directly
        /// or indirectly by a user's code. Managed and unmanaged resources can be disposed.
        /// If disposing equals false, the method has been called by the runtime from inside the finalizer 
        /// and you should not reference other objects. Only unmanaged resources can be disposed.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    updateTimer.Dispose();
                }
                disposed = true;
            }
        }

        #endregion
    }
}
